﻿using System;
using System.Collections.Generic;
using PluginSample2.BarModel;
using Plugins;
using Plugins.Base;
using StockModel;

namespace PluginSample2.Historical
{
	internal class DayProcessor : IDisposable
	{
		#region Attributes

		private readonly DateTime _day;
		private readonly Stock _stock;
		private readonly DataLoader _loader;
		private readonly DataFeeder _feeder;
		private readonly BarSourceSelector _selector;
		private readonly BarGenerator _barGenerator;
		private readonly DecissionEngine _decissionEngine;

		#endregion

		#region Properties

		public IEnumerable<Bar> Bars
		{
			get
			{
				return _barGenerator.Bars;
			}
		}

		#endregion

		#region Public Methods

		public DayProcessor(EngineSettings settings, DateTime day, Stock stock, QuotationDataSource quotationDataSource, RawStockDataSource rawStockDataSource, FakeOrderExecutor fakeOrderExecutor, OperationManager operationManager, DecisionEngineData engineData)
		{
			_day = day;
			_stock = stock;

			_loader = new DataLoader(quotationDataSource, rawStockDataSource, fakeOrderExecutor);
			_feeder = new DataFeeder(_loader.Data, settings);
			_selector = new BarSourceSelector(settings.BarSource, _feeder.Data);
			_barGenerator = new BarGenerator(_selector.Values, settings.BarDuration);
			_decissionEngine = new DecissionEngine(_barGenerator.Bars, _loader.Data, settings, operationManager, engineData);

			_loader.LastQuotation += this.Loader_LastQuotation; // Local object
		}

		public void Execute()
		{
			_loader.Load(_day, _stock);
		}

		#endregion

		#region Private Methods

		private void Loader_LastQuotation(object sender, EventArgs e)
		{
			_feeder.SetNextQuotationIsLastOne();
		}

		#endregion

		#region IDisposable

        protected bool Disposed { get; private set; }

        private void Dispose(bool disposing)
        {
            if (!this.Disposed)
            {
                this.InternalDispose(disposing);
            }

            this.Disposed = true;
        }

        protected virtual void InternalDispose(bool disposing)
        {
            if (disposing)
            {
				_feeder.Dispose();
			}

            // Dispose here only unmanaged objects 
            // Don’t use managed objects here because maybe 
            // they have been finalized already
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        ~DayProcessor()
        {
            this.Dispose(false);
        }

        #endregion

	}
}
